﻿using System;
using Jet.Utilities.Serialization;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Jet.Utilities.UnitTests
{
	/// <summary>
	/// Helper class to test constructors of custom exceptions
	/// </summary>
	public class TestsExceptionHelper
	{
		/// <summary>
		/// Test default .ctor of an exception.
		/// </summary>
		/// <typeparam name="T">Type of exception to test</typeparam>
		public static T TestExceptionDefaultCtor<T>() where T : Exception, new()
		{
			var e = new T();
			Assert.AreEqual(e.InnerException, null);
			Assert.IsNotNull(e.Message);
			return e;
		}

		/// <summary>
		/// Test .ctor with message param of an exception.
		/// </summary>
		/// <typeparam name="T">Type of exception to test</typeparam>
		public static T TestExceptionMessageCtor<T>() where T : Exception
		{
			const string st = "Exception Message";
			var e = (T)Activator.CreateInstance(typeof(T), st);
			Assert.AreEqual(e.InnerException, null);
			Assert.AreEqual(e.Message, st);
			return e;
		}

		/// <summary>
		/// Test .ctor with message and inner exception params of an exception.
		/// </summary>
		/// <typeparam name="T">Type of exception to test</typeparam>
		public static T TestExceptionMessageInnerCtor<T>() where T : Exception
		{
			const string st = "Exception Message";
			var inner = new ArgumentException("Test");
			var e = (T)Activator.CreateInstance(typeof(T), st, inner);
			Assert.AreEqual(e.InnerException, inner);
			Assert.AreEqual(e.Message, st);
			return e;
		}

		/// <summary>
		/// Test .ctor with message and inner exception params of an exception.
		/// </summary>
		/// <typeparam name="T">Type of exception to test</typeparam>
		public static T TestExceptionSerialization<T>(ISerializationService serializer) where T : Exception
		{
			const string st = "Exception Message";
			var inner = new ArgumentException("Test");
			var e = (T)Activator.CreateInstance(typeof(T), st, inner);
			var buffer = serializer.SerializeObject(e);
			e = serializer.DeserializeObject<T>(buffer);
			Assert.IsNotNull(e);
			Assert.IsNotNull(e.InnerException);
			Assert.AreEqual(e.InnerException.Message, inner.Message);
			Assert.AreEqual(e.InnerException.GetType(), inner.GetType());
			Assert.AreEqual(((ArgumentException)e.InnerException).ParamName, inner.ParamName);
			Assert.AreEqual(e.Message, st);
			return e;
		}

		/// <summary>
		/// Tests all standart ctors
		/// </summary>
		public static void TestAllExceptionCtors<T>(ISerializationService serializer) where T : Exception, new()
		{
			TestExceptionDefaultCtor<T>();
			TestExceptionMessageCtor<T>();
			TestExceptionMessageInnerCtor<T>();
			TestExceptionSerialization<T>(serializer);
		}

	}
}
